package com.qdlc.p2p.biz.service.impl;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.qd.p2p.adapter.Response;
import com.qd.p2p.adapter.enums.ResponseStatus;
import com.qd.p2p.sina.pay.enums.IdentityType;
import com.qdlc.p2p.biz.processor.event.RepayUpRateCollectNoticeEvent;
import com.qdlc.p2p.biz.processor.event.TppDispatchValueEvent;
import com.qdlc.p2p.biz.service.AbstractCollectService;
import com.qdlc.p2p.biz.service.RPCRequestService;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.NotifyUrl;
import com.qdlc.p2p.common.constant.SinaConstant;
import com.qdlc.p2p.common.constant.Summary;
import com.qdlc.p2p.common.constant.TradeCode;
import com.qdlc.p2p.common.constant.TradeStatus;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.core.queue.QueueHandlers;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.dao.TppDao;
import com.qdlc.p2p.dal.dao.TppTradeLogDao;
import com.qdlc.p2p.dal.dao.UpRateCollectionDao;
import com.qdlc.p2p.dal.dto.Borrow;
import com.qdlc.p2p.dal.dto.BorrowRepayment;
import com.qdlc.p2p.dal.dto.Tpp;
import com.qdlc.p2p.dal.dto.TppTradeLog;
import com.qdlc.p2p.dal.model.TppModel;
import com.qdlc.p2p.dal.model.TppTradeLogModel;

@Service("borrowRepayUpRateCollectService")
public class BorrowRepayUpRateCollectServiceImpl extends AbstractCollectService {

    private final static String BUSINESS_NAME = "还款代收加息-";

    /** 还款计划 */
    private ThreadLocal<BorrowRepayment> borrowRepaymentLocal = new ThreadLocal<BorrowRepayment>();

    /** 加息金额 */
    private ThreadLocal<Double> upRateSum = new ThreadLocal<Double>();
    
    /** 重新调度 */
    private ThreadLocal<Byte> autoDispatch = new ThreadLocal<Byte>();

    @Resource
    private UpRateCollectionDao upRateCollectionDao;

    @Resource
    private TppTradeLogDao tppTradeLogDao;

    @Resource
    private TppDao tppDao;

    @Resource
    @Qualifier("bfRPCRequestService")
    private RPCRequestService<Response, TppTradeLog> rpcRequestService;

    @Override
    public void analyzePars(Object... pars) {
        this.autoDispatch.set((byte)0);// 默认非自动
        if (pars.length != 1 && pars.length != 2) {
            throw new IllegalArgumentException("参数个数不正确!");
        }
        try {
            BorrowRepayment borrowRepayment = (BorrowRepayment) pars[0];
            if (borrowRepayment == null) {
                throw new IllegalArgumentException("参数类型不正确!");
            }
            this.borrowRepaymentLocal.set(borrowRepayment); // 还款计划
            if (pars.length == 2) {
            	this.autoDispatch.set((Byte) pars[1]);// 自动调度标识 1:自动,0:非自动
            }

            // 加息金额
            double upRateSumTemp = upRateCollectionDao.upRateCollectionSum(borrowRepayment.getBorrow().getId(), borrowRepayment.getPeriod());
            this.upRateSum.set(upRateSumTemp);
        } catch (Exception ex) {
            throw new IllegalArgumentException("参数类型正确!");
        }
    }

    @Override
    public TppTradeLog getTppTradeLog() {
        BorrowRepayment borrowRepayment = borrowRepaymentLocal.get();
        Borrow borrow = borrowRepayment.getBorrow();

        // TppTradeLog生成
        Map<String, Object> memoMap = new HashMap<String, Object>();
        memoMap.put("upRateTotal", upRateSum.get()); // 加息总额
        memoMap.put("period", borrowRepayment.getPeriod()); // 期数

        // 代收加息 利息
        TppTradeLog tppTradeLog = new TppTradeLog();
        tppTradeLog.setTppUserCustId(SystemConfigHelper.getSystemConfig(Nid.MERCHANT_ID).getValue()); // 平台支付
        tppTradeLog.setToTppUserCustId("0");
        tppTradeLog.setIdentityType(IdentityType.EMAIL.name());
        tppTradeLog.setMoney(upRateSum.get()); // 还款金额
        tppTradeLog.setBorrowId(borrow.getId()); // 标ID
        tppTradeLog.setBorrowRepaymentId(borrowRepayment.getId()); // 还款ID
        tppTradeLog.setMemo((new Gson()).toJson(memoMap));
        tppTradeLog.setTradeType(TradeCode.C1005.toString());
        tppTradeLog.setServiceType(Summary.REPAY.getSummaryType());
        tppTradeLog.setAutoDispatch(autoDispatch.get());// 自动调度标识 1:自动,0:非自动
        return tppTradeLog;
    }

    @Override
    public TppTradeLog createOrder(Object... pars) {
        analyzePars(pars);

        BorrowRepayment borrowRepayment = borrowRepaymentLocal.get();
        long borrowId = borrowRepayment.getBorrow().getId();

        // 根据期数及对应的标 获取加息总额(一般由加息券产生)
        int period = borrowRepayment.getPeriod(); // 期数
        double upRateSum = upRateCollectionDao.upRateCollectionSum(borrowId, period);
        if (upRateSum > 0) {
            // 防止重新发起代收时 会导致重复代收(处理中、已处理)
            boolean canReCreateOrder = tppTradeLogDao.canReCreateOrder(borrowId, borrowRepayment.getId(), TradeCode.C1005.getCode());
            if (canReCreateOrder) {
                return super.createOrder(pars);
            }
        }
        return null;
    }

    @Override
    public ReturnResult requestOrder(TppTradeLog tppTradeLog) {
        Response response = rpcRequestService.repayUpRateRequest(tppTradeLog);
        // 未知状态通知 交由消息队列处理
        if (response == null || response.getStatus() == ResponseStatus.UN_KNOW) {
            notice(tppTradeLog, TradeStatus.TRADE_STATUS_UN_KNOW);
            return new ReturnResult(true, "系统处理中!请查看投标结果!");
        }
        if (response.getStatus() == ResponseStatus.SUCCESS) {
            tppTradeLog.setRemark(getBusinessName().concat("提交成功"));
            tppTradeService.update(tppTradeLog);
            // 成功通知
            notice(tppTradeLog, TradeStatus.TRADE_STATUS_FINISHED);
            requestOrderSuccess(tppTradeLog); // 请求成功处理
        } else {
            String message = response == null ? "RPC调用失败" : MessageFormat.format("{0}代收失败!ResCode:{1} ResMessage:{2}",
                    response.getResponseCode(),
                    response.getResponseMsg());
            String responseMessage = response == null ? "RPC调用失败" : response.getResponseMsg();
            logger.info(message);

            // 置为废单
            tppTradeLog.setTradeStatus(TradeStatus.TRADE_STATUS_INVALID.getStatus());
            tppTradeLog.setRemark(getBusinessName().concat("提交失败-" + responseMessage));
            tppTradeService.update(tppTradeLog);

            requestOrderFail(tppTradeLog); // 请求失败处理
            return new ReturnResult(true, message);
        }
        return ReturnResult.SUCCESS;
    }

    @Override
    public void requestOrderFail(TppTradeLog tppTradeLog) {
        // 保存调度任务信息
        Tpp tpp = new Tpp();
        tpp.setStatus(TppModel.STATUS_FAIL);
        tpp.setServiceType(TppModel.DOREPAY);
        tpp.setTppType(SinaConstant.TRADE_SERVICE_REPAY);
        tpp.setTppUserCustId(SystemConfigHelper.getValue(Nid.MEMBER_EMAIL));// 平台的新浪标识
        tpp.setMoney(tppTradeLog.getMoney());
        tpp.setOrderId(tppTradeLog.getOrderNo());
        tpp.setOrderDate(DateUtil.dateStr7(tppTradeLog.getAddTime()));
        tpp.setExtended(tppTradeLog.getBorrowRepaymentId() + "");// 还款ID
        tpp.setTradeType(tppTradeLog.getTradeType());
        tpp.setRespDesc(tppTradeLog.getRemark());
        tpp.setAddTime(DateUtil.getNow());
        tpp.setTppBorrowId(tppTradeLog.getBorrowId() + "");// 标ID
        tppDao.save(tpp);
        
        // 调度任务交由队列处理(延时处理)
        if (tppTradeLog.getAutoDispatch() != TppTradeLogModel.IS_AUTO) {// 防止重复处理
        	TppModel tppModel = TppModel.instance(tpp);
        	TppDispatchValueEvent tppDispatchValueEvent = new TppDispatchValueEvent();
        	tppDispatchValueEvent.setTppModel(tppModel);
            QueueHandlers.put(tppDispatchValueEvent);
        }
    }

    /**
     * 还款代收 加息 完成
     */
    @Override
    public void tradeFinish(TppTradeLog tppTradeLog, String depositStatus, double tradeAmount) {
        super.tradeFinishForStatus(tppTradeLog, depositStatus, tradeAmount);
    }

    /**
     * 还款代收 本息 成功
     */
    @Override
    public void tradeSuccess(TppTradeLog tppTradeLog, String depositStatus) {
        tradeSuccessForStatus(tppTradeLog, depositStatus);
    }

    /**
     * 还款代收 本息 失败
     */
    @Override
    public void tradeFail(TppTradeLog tppTradeLog, String depositStatus) {
        tradeFailForStatus(tppTradeLog, depositStatus);
        // 加息代收失败
        requestOrderFail(tppTradeLog);
    }

    @Override
    public String getCallBackUrl() {
        return WEB_URL.concat(NotifyUrl.REPAY_NOTIFY_UP_RATE_COLLECT_URL).concat(".html");
    }

    @Override
    public String getBusinessName() {
        return BUSINESS_NAME;
    }

    /**
     * 发送投标通知 交由队列来执行
     */
    private void notice(TppTradeLog tppTradeLog, TradeStatus tradeStatus) {
        RepayUpRateCollectNoticeEvent event = new RepayUpRateCollectNoticeEvent();
        event.setClientIp(Global.getIP());
        event.setTradeStatus(tradeStatus);
        event.setTppTradeLog(tppTradeLog);
        event.setOutOrderNo(tppTradeLog.getOrderNo());
        event.setDepositAmount(tppTradeLog.getMoney());
        QueueHandlers.put(event);
    }
}
